﻿using System;
using System.Collections;
using System.IO;
using System.Windows;
using System.Xml.Serialization;
using System.Diagnostics;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
using MWin32Api;

namespace SQLVis.Vizualizador
{
public class AppConfigurationClass
{
    public bool ShowConsoleFlag;
    public bool SyncronousLineReadsFlag;
    public bool AnimateDirectoryLoadingFlag;
    public int  HighWaterMark;
    public int  LowWaterMark;
}

public partial class App: System.Windows.Application
{
    SafeFileHandle ConsoleHandle;

    /// <summary>
    /// Initialize the Win32 console for this process.
    /// </summary>
    private void InitWin32Console()
    {
        if ( !UserProperties.ShowConsoleFlag ) {
            return;
        }

        if ( !K32.AllocConsole() ) {
            return;
        }
        IntPtr handle = K32.CreateFile(
                             "CONOUT$",                                    // name
                             K32.GENERIC_WRITE | K32.GENERIC_READ,         // desired access
                             K32.FILE_SHARE_WRITE | K32.FILE_SHARE_READ,   // share access
                             null,                                         // no security attributes
                             K32.OPEN_EXISTING,                            // device already exists
                             0,                                            // no flags or attributes
                             IntPtr.Zero );                                // no template file.

        ConsoleHandle = new SafeFileHandle( handle, true );

        if ( ConsoleHandle.IsInvalid ) {
            MessageBox.Show( "Cannot create diagnostic console",
                             "SQLVis.Vizualizador Error",
                             MessageBoxButton.OK,
                             MessageBoxImage.Error );
            return;
        }

        //
        // Set the console screen buffer and window to a reasonable size
        //  1) set the screen buffer sizse
        //  2) Get the maximum window size (in terms of characters) 
        //  3) set the window to be this size
        //
        const UInt16 conWidth     = 256;
        const UInt16 conHeight    = 5000;

        K32.Coord dwSize = new K32.Coord( conWidth, conHeight );
        if ( !K32.SetConsoleScreenBufferSize( ConsoleHandle.DangerousGetHandle(), dwSize ) ) {
            MessageBox.Show( "Can't get console screen buffer information.",
                             "SQLVis.Vizualizador Error",
                             MessageBoxButton.OK,
                             MessageBoxImage.Error );
            return;
        }

        K32.Console_Screen_Buffer_Info SBInfo = new K32.Console_Screen_Buffer_Info();
        if ( !K32.GetConsoleScreenBufferInfo( ConsoleHandle.DangerousGetHandle(), out SBInfo ) ) {
            MessageBox.Show( "Can't get console screen buffer information.",
                             "SQLVis.Vizualizador Error",
                             MessageBoxButton.OK,
                             MessageBoxImage.Exclamation );
            return;
        }

        K32.Small_Rect sr; ;
        sr.Left   = 0;
        sr.Top    = 0;
        sr.Right  = 132 - 1;
        sr.Bottom = 51 - 1;

        if ( !K32.SetConsoleWindowInfo( ConsoleHandle.DangerousGetHandle(), true, ref sr ) ) {
            MessageBox.Show( "Can't set console screen buffer information.",
                             "SQLVis.Vizualizador Error",
                             MessageBoxButton.OK,
                             MessageBoxImage.Error );
            return;
        }

        IntPtr conHWND = K32.GetConsoleWindow();

        if ( conHWND == IntPtr.Zero ) {
            MessageBox.Show( "Can't get console window handle.",
                             "SQLVis.Vizualizador Error",
                             MessageBoxButton.OK,
                             MessageBoxImage.Error );
            return;
        }

        if ( !U32.SetForegroundWindow( conHWND ) ) {
            MessageBox.Show( "Can't set console window as foreground.",
                             "SQLVis.Vizualizador Error",
                             MessageBoxButton.OK,
                             MessageBoxImage.Error );
            return;
        }

        K32.SetConsoleTitle( "SQLVis.Vizualizador - Console" );

        Trace.Listeners.Add( new ConsoleTraceListener() );
    }

    /// <summary>
    /// Called on applicatin startup
    /// </summary>
    /// <param name="args">the command line arguments</param>
    protected override void
    OnStartup( StartupEventArgs args )
    {
        base.OnStartup( args );

        //
        // Load the user's preference settings
        //
        UserProperties = new SQLVis.Vizualizador.Properties.Settings();

        //
        // Setup the console window and send trace and 
        // debug messages to the console
        InitWin32Console(); 

        Trace.WriteLine( "> Command Line='{0}'", Environment.CommandLine );

        //
        // Compute the directory name for our configuration data and the file
        // name for the recently opened files list
        //
        ConfigDir           = Path.Combine( 
                                   Environment.GetFolderPath( Environment.SpecialFolder.LocalApplicationData ),
                                   "SQLVis.Vizualizador.Configuration" );
        RecentFilesFileName = Path.Combine( ConfigDir, "RecentFiles.AppState.xml" );


        // 
        // If the configuration directory doesn't exist then create it.
        //
        if ( !Directory.Exists( ConfigDir ) ) {
            try { 
                Directory.CreateDirectory( ConfigDir );
            } catch( Exception e ) {
                MessageBox.Show( 
                          "Cannot Create Application configuration directory", 
                          "SQLVis.Vizualizador Error", 
                          MessageBoxButton.OK,
                          MessageBoxImage.Error );
                Console.WriteLine( "Cannot create applicatoin configurion directory\n{0}\n\n", e.ToString() );
                //(?)  How do we terminate the applicatoin if this fails?
            }
        }

        //
        // Load the recent files list
        //
        if ( File.Exists( RecentFilesFileName ) ) {
            try {
                XmlSerializer ser = new XmlSerializer( typeof( ArrayList ) );
                TextReader reader = new StreamReader( RecentFilesFileName );
                RecentFiles = (ArrayList)ser.Deserialize( reader );
                reader.Close();
            }
            catch ( Exception e) {
                //(!) Log an app error here....
                MessageBox.Show( "Cannot load recently opened file list",
                          "SQLVis.Vizualizador Error",
                          MessageBoxButton.OK,
                          MessageBoxImage.Error );
                Console.WriteLine( "Cannot load the recently opened file list\n{0}\n\n", e.ToString() );
                RecentFiles.Clear();
            }
        }

        //
        // Remove files that no longer exist from the recent files list
        //
        for ( int i = RecentFiles.Count-1; i >= 0; --i ) {
            if ( !File.Exists( (String)RecentFiles[ i ] ) ) {
                RecentFiles.RemoveAt( i );
            }
        }
    }

    public void SaveConfigIfDirty()
    {
        if ( UserProperties.DirtyFlag ) {
            UserProperties.Save();
        }
    }

    protected override void
    OnExit( ExitEventArgs args )
    {
        try {
            SaveConfigIfDirty();

            XmlSerializer ser = new XmlSerializer( typeof( ArrayList ) );
            TextWriter writer = new StreamWriter( RecentFilesFileName );
            ser.Serialize( writer, RecentFiles );
            writer.Close();
        }
        catch ( Exception ) {
            //(!) Log an app error here....
            MessageBox.Show( "Cannot save recently opened file list",
                      "SQLVis.Vizualizador Error",
                      MessageBoxButton.OK,
                      MessageBoxImage.Error );
        }

        base.OnExit( args );
    }

    public     String  ConfigDir;
    public  ArrayList  RecentFiles = new ArrayList();
    private    String  RecentFilesFileName;

    internal SQLVis.Vizualizador.Properties.Settings UserProperties;

} // end class App
} // end namespace clv
